{
 "cells": [
  {
   "cell_type": "raw",
   "id": "1ea1fe24-fe1e-463b-a52c-79f0ef02328e",
   "metadata": {},
   "source": [
    "---\n",
    "sidebar_position: 2\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "95982bf1-7d9d-4dd6-a4ad-9de0719fe17f",
   "metadata": {},
   "source": [
    "# Choosing between multiple tools\n",
    "\n",
    "In our [Quickstart](/docs/use_cases/tool_use/quickstart) we went over how to build a Chain that calls a single `multiply` tool. Now let's take a look at how we might augment this chain so that it can pick from a number of tools to call. We'll focus on Chains since [Agents](/docs/use_cases/tool_use/agents) can route between multiple tools by default."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3fafec38-443a-42ad-a913-5be7667e3734",
   "metadata": {},
   "source": [
    "## Setup\n",
    "\n",
    "We'll need to install the following packages for this guide:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "78411bf1-0117-4f33-a3d7-f3d77a97bb78",
   "metadata": {},
   "outputs": [],
   "source": [
    "%pip install --upgrade --quiet langchain langchain-openai"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "59d08fd0-ddd9-4c74-bcea-a5ca3a86e542",
   "metadata": {},
   "source": [
    "And set these environment variables:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4185e74b-0500-4cad-ace0-bac37de466ac",
   "metadata": {},
   "outputs": [],
   "source": [
    "import getpass\n",
    "import os\n",
    "\n",
    "os.environ[\"OPENAI_API_KEY\"] = getpass.getpass()\n",
    "\n",
    "# If you'd like to use LangSmith, uncomment the below\n",
    "# os.environ[\"LANGCHAIN_TRACING_V2\"] = \"true\"\n",
    "# os.environ[\"LANGCHAIN_API_KEY\"] = getpass.getpass()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d28159f5-b7d0-4385-aa44-4cd1b64507bb",
   "metadata": {},
   "source": [
    "## Tools\n",
    "\n",
    "Recall we already had a `multiply` tool:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "e13ec98c-8521-4d63-b521-caf92da87b70",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.tools import tool\n",
    "\n",
    "\n",
    "@tool\n",
    "def multiply(first_int: int, second_int: int) -> int:\n",
    "    \"\"\"Multiply two integers together.\"\"\"\n",
    "    return first_int * second_int"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3de233af-b3bd-4f0c-8b1a-83527143a8db",
   "metadata": {},
   "source": [
    "And now we can add to it a `exponentiate` and `add` tool:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "e93661cd-a2ba-4ada-91ad-baf1b60879ec",
   "metadata": {},
   "outputs": [],
   "source": [
    "@tool\n",
    "def add(first_int: int, second_int: int) -> int:\n",
    "    \"Add two integers.\"\n",
    "    return first_int + second_int\n",
    "\n",
    "\n",
    "@tool\n",
    "def exponentiate(base: int, exponent: int) -> int:\n",
    "    \"Exponentiate the base to the exponent power.\"\n",
    "    return base**exponent"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bbea4555-ed10-4a18-b802-e9a3071f132b",
   "metadata": {},
   "source": [
    "The main difference between using one Tool and many, is that in the case of many we can't be sure which Tool the model will invoke. So we cannot hardcode, like we did in the [Quickstart](/docs/use_cases/tool_use/quickstart), a specific tool into our chain. Instead we'll add `call_tool_list`, a `RunnableLambda` that takes the `JsonOutputToolsParser` output and actually builds the end of the chain based on it, meaning it appends the Tools that were envoked to the end of the chain at runtime. We can do this because LCEL has the cool property that in any Runnable (the core building block of LCEL) sequence, if one component returns more Runnables, those are run as part of the chain."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "c35359ae-a740-48c5-b5e7-1a377fb25aa2",
   "metadata": {},
   "outputs": [],
   "source": [
    "from operator import itemgetter\n",
    "from typing import Union\n",
    "\n",
    "from langchain.output_parsers import JsonOutputToolsParser\n",
    "from langchain_core.runnables import (\n",
    "    Runnable,\n",
    "    RunnableLambda,\n",
    "    RunnableMap,\n",
    "    RunnablePassthrough,\n",
    ")\n",
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "model = ChatOpenAI(model=\"gpt-3.5-turbo\")\n",
    "tools = [multiply, exponentiate, add]\n",
    "model_with_tools = model.bind_tools(tools)\n",
    "tool_map = {tool.name: tool for tool in tools}\n",
    "\n",
    "\n",
    "def call_tool(tool_invocation: dict) -> Union[str, Runnable]:\n",
    "    \"\"\"Function for dynamically constructing the end of the chain based on the model-selected tool.\"\"\"\n",
    "    tool = tool_map[tool_invocation[\"type\"]]\n",
    "    return RunnablePassthrough.assign(output=itemgetter(\"args\") | tool)\n",
    "\n",
    "\n",
    "# .map() allows us to apply a function to a list of inputs.\n",
    "call_tool_list = RunnableLambda(call_tool).map()\n",
    "chain = model_with_tools | JsonOutputToolsParser() | call_tool_list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "ea6dbb32-ec9b-4c70-a90f-a2db93978cf1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'type': 'multiply',\n",
       "  'args': {'first_int': 23, 'second_int': 7},\n",
       "  'output': 161}]"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain.invoke(\"What's 23 times 7\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "b1c6c0f8-6d04-40d4-a40e-8719ca7b27c2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'type': 'add',\n",
       "  'args': {'first_int': 1000000, 'second_int': 1000000000},\n",
       "  'output': 1001000000}]"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain.invoke(\"add a million plus a billion\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "ce76f299-1a4d-421c-afa4-a6346e34285c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'type': 'exponentiate',\n",
       "  'args': {'base': 37, 'exponent': 3},\n",
       "  'output': 50653}]"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain.invoke(\"cube thirty-seven\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "poetry-venv",
   "language": "python",
   "name": "poetry-venv"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
